﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace SharePointGurus.Utility
{
    /// <summary>
    /// Represents a SharePoint folder. Allows for easily creating a subfolder and assigning permissions.
    /// </summary>
    class Folder
    {
        public string Path;     // the path to the subfolder. This is relative to the top of the document library
        private SPDocumentLibrary Library;  // the document library the folder exists in
        private SPFolder thisFolder;    // the SharePoint folder object that represents the folder
        
        /// <summary>
        /// Constructor for creating a sub folder. If the folder already exists, then it references the existing folder
        /// </summary>
        /// <param name="folderPath">The relative path to the folder requested</param>
        /// <param name="targetLibrary">The document library object where the folder should be created</param>
        public Folder(string folderPath, SPDocumentLibrary targetLibrary)
        {
            Path = folderPath + "/";
            Library = targetLibrary;        
            thisFolder = getFolder(Path);            
        }

        public void ResetPermissions()
        {
            //Discard any permissions already applied to this folder
            thisFolder.Item.ResetRoleInheritance();
            thisFolder.Item.BreakRoleInheritance(false);
            thisFolder.Item.Update();
        }

        /// <summary>
        /// Grants permissions to this folder object. Causes the folder to stop inheriting permissions. 
        /// If the folder already has custom permissions they are discarded
        /// </summary>
        /// <param name="accountName">The AD user, group or the SharePoint group to grant permissions to</param>
        /// <param name="permissionLevel">the name of the permission level the account should be granted</param>
        public void GrantPermissions(string accountName, string permissionLevel)
        {            
            // Associate the account with the permission level. If the account is not already a member of the site collection, they will be added at this stage
            SPUser account = Library.ParentWeb.EnsureUser(accountName);
            SPRoleAssignment assignRole = new SPRoleAssignment(account);
            SPRoleDefinition defineRole = Library.ParentWeb.RoleDefinitions[permissionLevel];
            assignRole.RoleDefinitionBindings.Add(defineRole);

            // Assign the account-role to the folder
            thisFolder.Item.RoleAssignments.Add(assignRole);   //Adds the specified account-role combination to the item
            thisFolder.Item.Update();
        
            return;
        }

        /// <summary>
        /// Returns a reference to a specified folder. If the folder doesn't exist, then it is created.
        /// This method can be called to create all intermediate subfolders needed to create the specified folder.
        /// </summary>
        /// <param name="folderUrl">The path to the folder requested</param>
        /// <returns>The SharePoint folder object representing the folder</returns>
        private SPFolder getFolder(string folderUrl)
        {
            //If an empty string is passed in, return a reference to the top level folder in the library
            if (string.IsNullOrEmpty(folderUrl))
                return Library.RootFolder;

            //Attempt to reference the folder requested
            SPFolder folder = Library.ParentWeb.GetFolder(Library.RootFolder.Url + "/" + folderUrl);

            if (!folder.Exists)
            {
                //The folder doesn't exist yet, check each folder in the path, creating them as required

                //Ensure that we can create subfolders
                if (!Library.EnableFolderCreation)
                {
                    Library.EnableFolderCreation = true;
                    Library.Update();
                }

                // Create an array of the folders in the path to the required sub folder
                string[] folders = folderUrl.Trim('/').Split('/');

                // Walk through the path to the destination subfolder
                string folderPath = string.Empty;
                for (int i = 0; i < folders.Length; i++)
                {
                    folderPath += "/" + folders[i];
                    folder = Library.ParentWeb.GetFolder(Library.RootFolder.Url + folderPath);
                    if (!folder.Exists)
                    {
                        // Found a missing part of the path. Create the subfolder.
                        SPListItem newFolder = Library.Items.Add("", SPFileSystemObjectType.Folder, folderPath.Trim('/'));
                        newFolder.Update();
                        folder = newFolder.Folder;
                    }
                }
            }

            // Still no folder so error out
            if (folder == null)
                throw new SPException(string.Format("The folder '{0}' could not be found.", folderUrl));
            return folder;
        }
    }
}
